package org.jslaughter.component.weapon;

import org.jslaughter.component.action.WeaponAction;
import org.jslaughter.component.physics.motion.BulletMotion;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Input;
import org.newdawn.slick.geom.Vector2f;
import org.nvframe.camera.Camera;
import org.nvframe.component.state.Position;
import org.nvframe.entity.Entity;
import org.nvframe.event.EventService;
import org.nvframe.event.eventtype.SoundEvent;
import org.nvframe.event.eventtype.UpdateEvent;
import org.nvframe.exception.NVFrameException;
import org.nvframe.factory.EntityFactory;
import org.nvframe.manager.ConfigManager;
import org.nvframe.manager.InputManager;
import org.nvframe.util.NVMathUtils;
import org.nvframe.util.settings.SettingsObj;

/**
 * 
 * @author Nik Van Looy
 */
public class ShotgunAction extends WeaponAction {

	private int shotgunShots;
	private String afterReloadSound;
	private float minDiffAngle;
	private float maxDiffAngle;
	
	public ShotgunAction(String id, Entity owner, SettingsObj settings) throws NVFrameException {
		super(id, owner, settings);

		shotgunShots = settings.getInt("shotgunShots", 5);
		minDiffAngle = settings.getFloat("minDiffAngle", 2.0f);
		maxDiffAngle = settings.getFloat("maxDiffAngle", 2.0f);
		afterReloadSound = settings.getString("afterReloadSound", null);
		
		if(shotgunShots % 2 == 0)
			throw new NVFrameException("shotgunShots must be uneven");
	}
	
	/**
	 * 
	 * 
	 * @param targetCoords
	 * @param diffAngle
	 * @throws NVFrameException
	 */
	private void generateBullets(Vector2f targetCoords) throws NVFrameException {

		Position position = (Position) owner.getComponent(Position.class);
		
		float radDirection = (float) Math.atan2(targetCoords.getY() - position.getY(), 
				targetCoords.getX() - position.getX());
		float diffAngle = NVMathUtils.getRandomNumberBetween(minDiffAngle, maxDiffAngle);
		float bulletAngle = (float) (Math.toDegrees(radDirection) - ((shotgunShots - 1) / 2 * diffAngle));
		
		Vector2f bulletPos = new Vector2f();
		
		for(int i = 0; i < shotgunShots; i++) {
			bulletPos.set(position.getX() + (float) Math.cos(Math.toRadians(bulletAngle)) * (position.getWidth()/2), 
					position.getY() + (float) Math.sin(Math.toRadians(bulletAngle)) *  (position.getHeight()/2));
			
			// create the bullet entity
			Entity bullet = EntityFactory.getInstance().getEntityFromPrototype(bulletId);
			bullet.setOwner(owner);
			
			BulletMotion entityMotionComp = (BulletMotion) bullet.getComponent(BulletMotion.class);
			entityMotionComp.fire(position.getXY().copy(), bulletPos.copy());
			
			diffAngle = NVMathUtils.getRandomNumberBetween(minDiffAngle, maxDiffAngle);
			bulletAngle += diffAngle;
		}
	}

	@Override
	public void onUpdate(UpdateEvent event) {
		GameContainer gc = event.getGc();
		int delta = event.getDelta();
		Input input = gc.getInput();
		
		shotTimerMs += delta;
		
		if(input.isKeyPressed(InputManager.getInstance().getInput("player_interaction_reload"))) {
			reloading = true;
			currReloadTimeMs = 0;			
			return;
		}
		
		if(reloading) {
			currReloadTimeMs += delta;
			
			if(currReloadTimeMs > reloadTimeMs) {
				remainingCap++;

				EventService.getInstance().fireEvent(new SoundEvent(reloadSound));
				
				currReloadTimeMs = 0;
				
				if(ConfigManager.getInstance().getActive("debugMode"))
					System.out.println("reloading, cap: " + remainingCap);
				
				if(remainingCap >= magazineCap) {
					reloading = false;

					// play reload sound
					if(afterReloadSound != null)
						EventService.getInstance().fireEvent(new SoundEvent(afterReloadSound));
				}
			}
			
			return; // can't shoot while reloading the shotgun with a shell
		}
		
		if(input.isMouseButtonDown(InputManager.getInstance().getInput("player_interaction_primaryfire"))) {
			// stop reloading when shooting
			reloading = false;
			
			if(shotTimerMs < shotDelayMs || remainingCap <= 0)
				return;
			
			Vector2f targetCoords = new Vector2f(Camera.getInstance().getMouseX(input), Camera.getInstance().getMouseY(input));

			try {
				// emit the bullets
				generateBullets(targetCoords);
				
				EventService.getInstance().fireEvent(new SoundEvent(shotSound));

				remainingCap--;
				
				if(ConfigManager.getInstance().getActive("debugMode"))
					System.out.println("remainingCap: " + remainingCap);
			} 
			catch(NVFrameException ee) {
				ee.printStackTrace();
			}
			
			if(remainingCap == 0) {
				reloading = true;
				currReloadTimeMs = 0;
			}
			else
				shotTimerMs = 0;
		}
	}

}
